/* 公用方法，其他项目可直接复用 */
const regeneratorRuntime = require('../vendor/runtime');
/**
 * 将 Map 转为 Object
 * @param {Map} map
 * @returns {Object}}
 * **/

export const mapToObj = (map) => {
  if (map.constructor !== Map) {
    throw new Error('参数类型不为Map类型');
  }
  let temp = {};
  for (const [k, v] of map) {
    temp[k] = v;
  }
  return temp;
}

/**
 * 将 Object 转为 Map
 * @param {Object} obj
 * @returns {Map}
 * **/

export const objToMap = (obj) => {
  if (obj.constructor !== Object) {
    throw new Error('参数类型不为Object类型');
  }
  let temp = new Map();
  for (const [k, v] of Object.entries(obj)) {
    temp.set(k, v);
  }
  return temp;
}

/**
 * 将对象数组中的特定key转换为对象
 * @param {Object[]} arr
 * @param {String} key
 * @returns {Object}
 * **/

export const arrObjToObj = (arr, key) => {
  if (!Array.isArray(arr)) {
    throw new Error('参数arr类型不为Array类型');
  }
  let temp = {};
  arr.forEach(item => {
    if (item[key] === undefined) {
      return;
    }
    temp[item[key]] = item;
  });
  return temp;
}


/**
 * 深克隆
 *
 * @param {object} obj 要复制的对象
 *
 * @returns {object}
 */
export const deepClone = (obj) => {
  var _toString = Object.prototype.toString;

  // null, undefined, non-object, function
  if (!obj || typeof obj !== 'object') {
    return obj;
  }

  // DOM Node
  if (obj.nodeType && 'cloneNode' in obj) {
    return obj.cloneNode(true);
  }

  // Date
  if (_toString.call(obj) === '[object Date]') {
    return new Date(obj.getTime());
  }

  // RegExp
  if (_toString.call(obj) === '[object RegExp]') {
    var flags = [];
    if (obj.global) { flags.push('g'); }
    if (obj.multiline) { flags.push('m'); }
    if (obj.ignoreCase) { flags.push('i'); }

    return new RegExp(obj.source, flags.join(''));
  }

  var result = Array.isArray(obj) ? [] :
    obj.constructor ? new obj.constructor() : {};

  for (var key in obj) {
    result[key] = deepClone(obj[key]);
  }

  return result;
}


/**
 * 字段检验
 *
 * @param {Object} params 需要检验的参数对象
 * {
 *   k1: v1,
 *   k2: v2
 * }
 * @param {Object} rule 校验规则
 * {
 *  k1: [
 *    {
 *      useFnName: 'require',
 *      msg: '不能为空'
 *    }
 *  ]
 * }
 *
 * @returns {Object} {
 *    result 校验结果
 *    field  第一个检验不通过的字段
 *  }
 */
export const validator = (params, rule) => {
  let _params = params || {};
  let _rule = rule || {};
  if (!Object.keys(_params).length || !Object.keys(_rule).length) {
    return true;
  }
  let ruleFn = getRuleFn();
  let result = true;
  let field = '';
  for (let key in _rule) {
    if (!_params.hasOwnProperty(key)) {
      continue;
    }
    for (var i = 0; i < _rule[key].length; i++) {
      let item = _rule[key][i];
      if (typeof item.useFnName === 'string' && ruleFn[item.useFnName]) {
        if (!ruleFn[item.useFnName](_params[key])) {
          wx.showToast({
            title: item.msg,
            icon: 'none'
          });
          field = key;
          break;
        }
      } else {
        throw new Error('未定义检验函数');
      }
    }
    if (i !== _rule[key].length) {
      result = false;
      break;
    }

  }
  return {
    result,
    field
  };
}

function getRuleFn() {
  return {
    'require': function (v) {
      if (typeof v === 'string') {
        return !!v;
      } else if (typeof v === 'object') {
        if (v.constructor === 'Array') {
          return !!v.length
        } else {
          return !!Object.keys(v).length
        }
      } else if (typeof v === 'number') {
        return true;
      }

    },
    'isMobile': function (v) {
      let reg = /^1[3,4,5,6,7,8,9]\d{9}$/;
      return reg.test(v);
    },
    'isTel': function (v) {
      let reg = /^(\d{2,4}[-_－—]?)?\d{3,8}([-_－—]?\d{3,8})?([-_－—]?\d{1,7})?$/;
      return reg.test(v);
    }
  }
}

/**
 * 类似于vue的watch
 *
 * @param {object} ctx page 的this
 * @param {object} obj 需要监听的值
 * {
 *   key: callback(newVale){}
 * }
 *
 *
 */
export const watch = (target, obj) => {
  Object.keys(obj).forEach((key) => {
    defineReactive(target, key, target[key], function (newVal) {
      obj[key](newVal);
    });
  });
}

function observe(obj, fn) {
  if (typeof obj === 'object') {
    for (var i in obj) {
      defineReactive(obj, i, obj[i], fn);
    }
  }
}

function defineReactive(data, key, val, fn) {
  observe(val, fn);
  Object.defineProperty(data, key, {
    configurable: true,
    enumerable: true,
    get: function () {
      return val
    },
    set: function (newVal) {
      if (newVal === val) return
      val = newVal
      fn && fn(newVal)
    },
  })
}

/**
 * 获取当前页面路径
 *
 * @returns {String} path
 */

export const getCurrentPagePath = function () {
  let pages = getCurrentPages();
  let page = pages[pages.length - 1];
  let pageRoute = page.route;
  let pageOptions = page.options || {};
  let args = Object.entries(pageOptions).reduce((res, [k, v], idx, arr) => res += `${k}=${v}${idx === arr.length - 1 ? '' : '&'}`, '');

  return `${pageRoute}${args ? '/?' + args : ''}`;
}

/**
 * 获取跳转到当前页面的path
 *
 * @returns {String} path
 */

export const getFromPath = function () {
  let pages = getCurrentPages();
  let idx = pages.length - 2 >= 0 ? pages.length - 2 : pages.length - 1;
  return pages[idx].route;
}

/**
 * 时间格式化
 *
 * @param {object} opt
 * {
 *   rule: 'y-M-d' 可选字符( y|Y, M, d|D, h|H, m, s|S ) 对应年、月、日、时、分、秒
 *   isPadding: true 是否补0，比如5月份 返回05
 * }
 * @param {object} date
 *   default: new Date()
 * @returns {string} 格式化时间的结果
 */
export const formatDate = (opt, date = new Date(), specical=false) => {
  const _toString = Object.prototype.toString;
  if (opt.toString() !== '[object Object]') {
    throw new Error('日期格式配置参数为object!');
  }
  let _rule = opt.rule || 'y-M-d';
  let _isPadding = opt.isPadding || true;
  let _date = null;

  if (typeof date === 'object' && _toString.call(date) === '[object Date]') {
    _date = date;
  } else {
    // 兼容ios
    _date = new Date(date.replace(/-/g, "/"));
    if (_date == 'Invalid Date') {
      throw new Error('无效的日期参数!');
    }
  }

  let result = '';

  if (specical) {
    const now = new Date();
    const nowYear = now.getFullYear();
    const nowMonth = now.getMonth() + 1;
    const nowDay = now.getDate();

    if(nowYear === _date.getFullYear()) {
      if (nowMonth === _date.getMonth() + 1) {
        if (nowDay === _date.getDate()) {
          result += '今天'
        }else if(nowDay === _date.getDate() + 1) {
          result += '昨天'
        }else {
          result += `${_date.getMonth() + 1}月${_date.getDate()}日`;
        }
        result += ` ${new String(_date.getHours()).padStart(2, '0')}:${new String(_date.getMinutes()).padStart(2, '0')}`
      }else {
        result += `${_date.getMonth() + 1}月${_date.getDate()}日 ${new String(_date.getHours()).padStart(2, '0')}:${new String(_date.getMinutes()).padStart(2, '0')}`
      }
    }
    return result
  }

  _rule.split('').forEach((item) => {
    let temp = '';
    if (item !== 'm' && item !== 'M') {
      temp = item.toLocaleLowerCase();
    } else {
      temp = item;
    }
    switch (temp) {
      case 'y':
        result += _date.getFullYear();
        break;
      case 'M':
        let M = _isPadding ? `${_date.getMonth() + 1}`.padStart(2, '0') : (_date.getMonth() + 1);
        result += M;
        break;
      case 'd':
        let d = _isPadding ? `${_date.getDate()}`.padStart(2, '0') : _date.getDate();
        result += d;
        break;
      case 'h':
        let h = _isPadding ? `${_date.getHours()}`.padStart(2, '0') : _date.getHours();
        result += h;
        break;
      case 'm':
        let m = _isPadding ? `${_date.getMinutes()}`.padStart(2, '0') : _date.getMinutes();
        result += m;
        break;
      case 's':
        let s = _isPadding ? `${_date.getSeconds()}`.padStart(2, '0') : _date.getSeconds();
        result += s;
        break;
      default:
        result += item;
    }
  });
  return result;

}

/**
 * 延迟
 *
 * @param {Number} time 单位 秒
 */
export const delay = (time) => new Promise((resolve, reject) => {
  setTimeout(resolve, time * 1000);
});

/**
 * 生成跳转参数
 *
 * @param {Object} query 要加入url里的参数
 */
export const encodeUrl = (query) => {
  let url = '?';
  Object.entries(query).forEach(([k, v]) => {
    url = url + `${k}=${encodeURIComponent(v)}&`;
  });
  return url.substr(0, url.length - 1);

}

/**
 * 转换参数
 *
 * @param {Object} query url里的参数
 */
export const decodeUrl = (query) => {
  const params = {};
  Object.entries(query).forEach(([k, v]) => {
    params[k] = decodeURIComponent(v);
  });
  return params;
}

/**
 * 格式化价格
 * @param {number} price 以分为单位的价格
 * @param {string|boolean} unit 是否带单位 例子：formatPrice(1002,true) 返回 ¥10.02
 * @return {string} 以元为单位的价格
 */
export const formatPrice = (price, unit) => {
  if (typeof unit === 'string') {
    return +(price / 100).toFixed(2) + unit;
  }
  if (typeof unit === 'boolean' && unit) {
    return `¥${+(price / 100).toFixed(2)}`;
  }
  return +(price / 100).toFixed(2);
};

export const formatParams = params => {
  Object.keys(params).forEach(key => {
    if ( params[key] === '' || params[key] === null || params[key] === undefined) {
      delete params[key]
    }
  })
  return params;
};
